/*
 * Project: push-center-service-impl
 * 
 * File Created at 2014-10-10
 * 
 * Copyright 2012 Greenline.com Corporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Greenline Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Greenline.com.
 */
package com.greenline.push.service.core;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.PriorityBlockingQueue;

import com.greenline.push.service.core.item.Packet;

/**
 * 推送的处理队列
 * 
 * @author weirui.shenwr
 * @date 2014-10-10
 * @version V1.0
 */
public class ProcessQueueList {

    private final int initialCapacity = 1000;
    private int maxRemainingCapacity = 10000;

    private List<PriorityBlockingQueue<Packet>> processQueueList;
    private int queueCount;

    public ProcessQueueList(int queueCount, int maxRemainingCapacity) {
        this.queueCount = queueCount;
        processQueueList = new ArrayList<PriorityBlockingQueue<Packet>>(queueCount);

        // 初始化处理队列
        Comparator<Packet> comparator = new Comparator<Packet>() {
            public int compare(Packet p1, Packet p2) {
                return p1.getPriority() - p2.getPriority();
            }
        };

        this.maxRemainingCapacity = maxRemainingCapacity;

        for (int i = 0; i < queueCount; i++) {
            processQueueList.add(new PriorityBlockingQueue<Packet>(initialCapacity, comparator));
        }
    }

    /**
     * Inserts the specified element into this priority queue.
     * 
     * @param e the element to add
     * @return <tt>true</tt> (as specified by {@link Queue#offer})
     * @throws ClassCastException if the specified element cannot be compared
     *             with elements currently in the priority queue according to
     *             the priority queue's ordering
     * @throws NullPointerException if the specified element is null
     */
    public boolean offer(Packet packet) {
        PriorityBlockingQueue<Packet> queue = getQueue(packet);
        if (queue.size() < maxRemainingCapacity) {
            return queue.offer(packet);
        } else {
            return false;
        }
    }

    /**
     * 根据数据参数hashcode获取，处理队列
     * 
     * @param packet
     * @return
     */
    private PriorityBlockingQueue<Packet> getQueue(Packet packet) {
        int queueIdx = Math.abs(packet.hashCode() % queueCount);
        return processQueueList.get(queueIdx);
    }

    public Packet take(int queueIndex) throws InterruptedException {
        if (queueIndex > queueCount) {
            throw new IllegalArgumentException("queueIndex (" + queueIndex + ") can't larger than queue count:"
                    + queueIndex);
        }
        Packet p = processQueueList.get(queueIndex).take();
        return p;
    }

    public List<PriorityBlockingQueue<Packet>> getProcessQueueList() {
        return processQueueList;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            Packet p = new Packet();
            int idx = (int) Math.floor(Math.random() * 5);
            System.out.println(idx);
            System.out.println(p.hashCode());
        }

    }
}
